package studiodiva.portfolio.client.lib.history;

import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.History;

import java.util.Map;

import static studiodiva.portfolio.client.lib.lang.Lang.iterate;
import static studiodiva.portfolio.client.lib.lang.Lang.map;
import static studiodiva.portfolio.client.lib.lang.Lang.no;
import static studiodiva.portfolio.client.lib.lang.Lang.set;
import static studiodiva.portfolio.client.lib.lang.Lang.text;

import studiodiva.portfolio.client.lib.collections.Mapped;
import studiodiva.portfolio.client.lib.lang.Base;
import studiodiva.portfolio.client.lib.lang.Text;
import studiodiva.portfolio.client.model.HasApplication;

public class HistoryItems extends Base {

  private final Map<String, HistoryItem> items = map();

  public HistoryItem create(String key, String defaultValue) {
    HistoryItem item = items.get(key);
    if (no(item)) {
      items.put(key, item = new HistoryItemImpl(key, defaultValue) {
        @Override
        public void save(String value) {
          super.save(value);
          onItemChange();
        }
      });
      item.initialize(this);
    }
    return item;
  }

  @Override
  public void initialize(HasApplication parent) {
    super.initialize(parent);
    History.addValueChangeHandler(new ValueChangeHandler<String>() {
      public void onValueChange(ValueChangeEvent<String> event) {
        loadHistory(event.getValue());
      }
    });
    loadHistory(History.getToken());
  }

  private void loadHistory(String historyToken) {
    if (historyToken.startsWith("!")) historyToken = historyToken.substring(1);
    try {
      for (String keyvalue : historyToken.split(":")) {
        String[] keyvalueSplit = keyvalue.split("=");
        items.get(keyvalueSplit[0]).load(keyvalueSplit[1]);
      }
    } catch (Exception e) {
      for (HistoryItem item : items.values())
        item.loadDefault();
    }
  }

  private void onItemChange() {
    saveHistory();
  }

  private void saveHistory() {
    Text token = text();
    for (Mapped<String, HistoryItem> item : iterate(items))
      token.add(item.key()).add("=").add(item.value().getValue()).add(":");
    if (set(token)) token.cutEnd(1);
    History.newItem("!" + token.toString(), false);
  }
}
